package com.matuw.androidx.fragment;

import android.view.View;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.matuw.android.ui.QComponent;

import java.util.List;

/**
 * @author Shihwan
 * @date 2023/8/21
 */
public abstract class LazyFragment extends Fragment implements QComponent, ILazyFragment {

    private boolean mInitialized;
    private boolean mVisible;

    public LazyFragment() {
    }

    public LazyFragment(int contentLayoutId) {
        super(contentLayoutId);
    }

    @Override
    public boolean isVisibleToUser() {
        return mVisible;
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchVisible();
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatchInvisible();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            dispatchInvisible();
        } else {
            dispatchVisible();
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            dispatchVisible();
        } else {
            dispatchInvisible();
        }
    }

    protected void dispatchVisible() {
        Fragment parent = getParentFragment();
        if (parent instanceof ILazyFragment && !((ILazyFragment) parent).isVisibleToUser()) {
            // Parent Fragment is invisible, child fragment must be invisible.
            return;
        }

        if (isResumed() && !isHidden() && getUserVisibleHint() && !isVisibleToUser()) {
            mVisible = true;

            if (mInitialized) {
                onVisibleToUser(false);
            } else {
                mInitialized = true;
                doOnCreate(null);
                onVisibleToUser(true);
            }
            dispatchChildFragmentVisible();
        }
    }

    protected void dispatchChildFragmentVisible() {
        List<Fragment> fragments = getChildFragmentManager().getFragments();
        for (Fragment fragment : fragments) {
            if (fragment instanceof LazyFragment) {
                ((LazyFragment) fragment).dispatchVisible();
            }
        }
    }

    protected void dispatchInvisible() {
        if (mVisible) {
            mVisible = false;
            onInvisibleToUser();
            dispatchChildFragmentInvisible();
        }
    }

    protected void dispatchChildFragmentInvisible() {
        List<Fragment> fragments = getChildFragmentManager().getFragments();
        for (Fragment fragment : fragments) {
            if (fragment instanceof LazyFragment) {
                ((LazyFragment) fragment).dispatchInvisible();
            }
        }
    }

    /**
     * fragment 可见
     */
    @Override
    public void onVisibleToUser(boolean first) {
    }

    @Override
    public void onInvisibleToUser() {
    }

    @Nullable
    @Override
    public <V extends View> V findViewById(int id) {
        View view = getView();
        return view == null ? null : view.findViewById(id);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mInitialized = false;
        mVisible = false;
    }

    @Override
    public void closeComponent() {
        if (isAdded()) {
            FragmentManager manager = getParentFragmentManager();
            FragmentTransaction ft = manager.beginTransaction();
            ft.remove(this);
            ft.commitAllowingStateLoss();
        }
    }
}
